#include "unitlistmodel.h"
#include "columnheader.h"

#include "collections/unitcollection.h"

// \TODO: Avoid use of defines

#define NAME_COLUMN 0
#define COST_COLUMN header->count()+1

UnitListModel::UnitListModel(const UnitCollection *_units, const ColumnHeader *_header,
                             QObject *parent) :
    QAbstractItemModel(parent)
{
    units = _units;
    header = _header;

    connect(header, SIGNAL(columnAboutToBeInserted()), this, SLOT(onColumnAboutToBeInserted()));
    connect(header, SIGNAL(columnInserted()), this, SLOT(onColumnInserted()));
    connect(header, SIGNAL(columnsAboutToBeCleared()), this, SLOT(onColumnsAboutToBeCleared()));
    connect(header, SIGNAL(columnsCleared()), this, SLOT(onColumnsCleared()));
}

UnitListModel::~UnitListModel() {
    clearUnits();
}

void UnitListModel::clearUnits() {
    if(rows.size() > 0) {
        beginRemoveRows(QModelIndex(), 0, rows.size() -1);

        qDeleteAll(rows);
        rows.clear();

        endRemoveRows();
    }
}

QVariant UnitListModel::data(const QModelIndex &index, int role) const {
    if(!index.isValid())
        return QVariant();

    UnitListModelItem *item = static_cast<UnitListModelItem*>(index.internalPointer());
    if(role == Qt::DisplayRole) {
        if(index.column() == NAME_COLUMN)
            return item->unit->getName();
        else if(index.column() == COST_COLUMN)
            return item->unit->getCost();
        else {
            HeaderColumn c(header->at(index.column() -1));
            QString ret = item->unit->cells.value(c.key, c.column->defaultValueAs);
            if(ret == c.column->defaultValue)
                ret = c.column->defaultValueAs;
            return ret;
        }
    } else if(role == Qt::UserRole) {
        return item->key;
    } else if (role == Qt::TextAlignmentRole) {
        if (index.column() != 0)
            return Qt::AlignCenter;
        else
            return Qt::AlignLeft + Qt::AlignVCenter;
    }

    return QVariant();
}

Qt::ItemFlags UnitListModel::flags(const QModelIndex &index) const {
    if (!index.isValid())
        return 0;

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant UnitListModel::headerData(int section, Qt::Orientation orientation,
                                   int role) const {
    if(orientation != Qt::Horizontal)
        return QVariant();
    if(section < 0 || section > header->count()+1)
        return QVariant();

    if(role == Qt::DisplayRole) {
        if(section == NAME_COLUMN)
            return tr("Name");
        else if(section == COST_COLUMN)
            return tr("Cost");
        else
            return header->at(section-1).column->getName();
    } else if(role == Qt::UserRole)
        return header->value(section-1).key;
    else
        return QVariant();
}

int UnitListModel::rowCount(const QModelIndex &parent) const {
    if(parent.isValid())
        return 0;
    return rows.size();
}

int UnitListModel::columnCount(const QModelIndex &parent) const {
    Q_UNUSED(parent)
    return header->count() + 2;
}

QModelIndex UnitListModel::index(int row, int column,
                                 const QModelIndex &parent) const {
    if(!hasIndex(row, column, parent))
        return QModelIndex();
    if(parent.isValid())
        return QModelIndex();

    UnitListModelItem *item = rows.at(row);
    if(item)
        return createIndex(row, column, item);
    else
        return QModelIndex();
}

QModelIndex UnitListModel::parent(const QModelIndex &index) const {
    Q_UNUSED(index)
    return QModelIndex();
}

void UnitListModel::addUnit(const QString& key) {
    Q_ASSERT(units->contains(key));
    beginInsertRows(QModelIndex(), rows.size(), rows.size());
    UnitListModelItem *item = new UnitListModelItem();
    item->key = key;
    item->unit = units->getRealElement(key);
    rows.append(item);
    endInsertRows();
}

QString UnitListModel::getUnitKey(int row) {
    if(row > -1 && row < rows.size()) {
        UnitListModelItem *item = rows.at(row);
        if(item)
            return item->key;
    }
    return QString();
}

void UnitListModel::onColumnAboutToBeInserted() {
    int column = header->count() + 1;
    beginInsertColumns(QModelIndex(), column, column);
}

void UnitListModel::onColumnInserted() {
    endInsertColumns();
}

void UnitListModel::onColumnsAboutToBeCleared() {
    beginRemoveColumns(QModelIndex(), 1, header->count());
}

void UnitListModel::onColumnsCleared() {
    endRemoveColumns();
}
